<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      class LegacySandbox {
        constructor() {
          /**
           * modifiedPropsMap，addPropsMap是对失活的时候，进行属性还原的
           */
          // 修改后，需要记录window上该属性的原值
          this.modifiedPropsMap = {};
          // 需要记录新增的内容
          this.addPropsMap = {};
          /**
           * currentPropsMap是用在激活时候，进行属性还原的
           */
          // 需要记录所有（不管修改还是新增），对于window上属性的删除就是修改
          this.currentPropsMap = {};

          // 创建了一个假 Window 对象，fakeWindow => {}
          const fakeWindow = Object.create(null);
          const proxy = new Proxy(fakeWindow, {
            get: (target, key, receiver) => {
              // 当取值的时候，直接从 window 上取值
              return window[key];
            },
            set: (target, key, value, receiver) => {
              if (!window.hasOwnProperty(key)) {
                // 如果 window 上没有这个属性，则记录新增的属性
                this.addPropsMap[key] = value;
              } else if (!this.modifiedPropsMap.hasOwnProperty(key)) {
                // 如果 window 上有这个属性，并且之前没有修改过，需要记录原 window 上的值
                this.modifiedPropsMap[key] = window[key];
              }
              // 无论新增还是修改，都记录一份（变化后的值）
              this.currentPropsMap[key] = value;
              // 修改window上的属性，修改成最新的内容
              window[key] = value;
            },
          });
          this.proxy = proxy;
        }
        active() {
          // 激活时，恢复之前的内容
          Object.keys(this.currentPropsMap).forEach((key) => {
            this.setWindowProps(key, this.currentPropsMap[key]);
          });
        }
        inactive() {
          // 失活的时候，需要把修改的属性还原回去
          Object.keys(this.modifiedPropsMap).forEach((key) => {
            this.setWindowProps(key, this.modifiedPropsMap[key]);
          });
          // 如果新增了属性，在失活时需要移除
          Object.keys(this.addPropsMap).forEach((key) => {
            this.setWindowProps(key, undefined);
          });
        }
        // 设置window上的属性
        setWindowProps(key, value) {
          if (value === undefined) {
            // 移除后面新增的属性
            delete window[key];
          } else {
            // 变回原来的初始值
            window[key] = value;
          }
        }
      }

      const sandbox = new LegacySandbox();
      // 需要去修改代理对象，代理对象setter后会去修改window上的属性
      sandbox.proxy.a = 100;
      console.log(window.a, sandbox.proxy.a); // 100 100
      sandbox.inactive();
      console.log(window.a, sandbox.proxy.a); // undefined undefined
      sandbox.active();
      console.log(window.a, sandbox.proxy.a); // 100 100
    </script>
  </body>
</html>
